///////////////////////////////////////////////////////////////////////
//  (c) Copyright Honeywell Inc. 2005, All rights reserved.
//
//      Honeywell Access Systems Confidential Proprietary 
//	This file contains proprietary information of Honeywell, Inc. 
//	and may not be copied or used without permission.  This copyright
//	notice does not imply publication.
///////////////////////////////////////////////////////////////////////


#ifndef __DBRECORD__
#define __DBRECORD__

#include "intTypes.h"  
#include <stdio.h>
#include <string.h>
#include <iconv.h>

struct ConfigTableHeader
{
  UINT8     TableID;
  UINT8     VersionNumber;
  UINT8     Type;
  UINT8    RecordSize[2];    
  UINT8    NumRecords[2];
  UINT8    PopulatedRecords[2];
};

enum TableTypes
{
  // boolean bit field in Type field
  CommonTable = 1,  // This is a common table
  PanelSpecificTable = 2,
  StatusTable = 3,
};

class DBRecord
{
public:
  enum  Constants
  {
    // Define Constants required by Header file Generation Utility
    BIT0 = 0x01,
    BIT1 = 0x02,
    BIT2 = 0x04,
    BIT3 = 0x08,
    BIT4 = 0x10,
    BIT5 = 0x20,
    BIT6 = 0x40,
    BIT7 = 0x80,
    nameSize = 26,

    // Other Constants
    // This is the database version number and should be updated whenever the spec files  are updated
    configDBVersion = 18,
    // The point number represents feature additions to the database that are backward
    // compatible withj ealier point releases of the same version number.
    configDBPointNumber=0,
  //NOTE: These strings must match the enum values define above!
#define ConfigDBMajorVersionString "18"
#define ConfigDBMinorVersionString "0"
  };


  enum TableIds
  {
    //
    // Card table is #1, but not implemented as a "config" DB see CardDB implementation.
    // Common Tables
    Card = 1,
    TimeZone = 2,
    CardFormat = 3,
    Holiday = 4,
    AccessLevel=5,
    SiteCode=15,
    Room = 28,

    // Panel Specific Tables
    Input = 6,
    Output = 7,
    OutputGroup = 8,
    Interlock = 9,
    AccessLevelDevice= 10,
    Reader = 11,                        
    Device = 12,
    PSOCConfiguration = 13, 
    PanelConfiguration = 14,
    Door = 16,


    // Status - Volatile  Tables
      SystemStatus = 17,
      DoorStatus = 18,
    InputStatus = 19,
    OutputStatus = 20,
    TimeZoneStatus = 21,
    DeviceStatus = 22, 
    PanelStatus = 23,
    RoomStatus = 24,
    ReaderStatus = 25,
    OutputGroupStatus = 26,
      ImageVersion = 27,

    numConfigTables=29		//This number has to be higher than the highest number table
  };

  enum TableSizes
  {
    // Common Tables
    numAccessLevelRecords=128,
    numTimeZoneRecords= 127,
    numCardFormatRecords= 128,
    numHolidayRecords= 255,
    numSiteCodeRecords= 8,
    numRoomRecords = 62,

    // Panel Specific Tables
    numAccessLevelDeviceRecords=128,
    numDeviceRecords= 16,
    numInputRecords= 128,
    numInterlockRecords= 256,
    numOutputRecords= 128,
    numOutputGroupRecords= 64,
    numPanelConfigurationRecords= 1,
    numPSOCConfigurationRecords= 14, 
    numImageVersionRecord = 9,
    numDoorRecords= 4,
    numReaderRecords= 8,

    // Status Tables
    numDeviceStatusRecords= numDeviceRecords, 
    numInputStatusRecords= numInputRecords,
    numRoomStatusRecords= numRoomRecords,
    numOutputStatusRecords= numOutputRecords,
    numPanelStatusRecords= 1,
    numSystemStatusRecords= 1,
    numDoorStatusRecords= numDoorRecords,
    numReaderStatusRecords= numReaderRecords,
    numTimeZoneStatusRecords= numTimeZoneRecords,
    numImageVersionRecords = 16,
  };

  // Set a 16 bit integer value
  static void Set16(UINT8 *p, UINT16 val)
  {
#if BIGENDIAN
    *(UINT16 *)(p) =val;
#else
    *p++ = (val &0xFF00) >> 8;
    *p = (val &0xFF);
#endif
  }

  // Get a 16 bit integer value
  static  UINT16 Get16(UINT8 *p)
  {
#if BIGENDIAN
    return(*(UINT16 *)p);
#else
    return((*p << 8) | *(p+1));
#endif
  }

  // Set a 32 bit integer value
  static void  Set32(UINT8 *p, UINT32 val)
  {
#if BIGENDIAN
    *(UINT32 *)(p) =val;
#else
    *p++ = (val & 0xFF000000) >> 24;
    *p++ = (val & 0xFF0000) >> 16;
    *p++ = (val & 0xFF00) >> 8;
    *p = (val &0xFF);
#endif
  };

  // Get a 16 bit integer value
  static UINT32 Get32(UINT8 *p)
  {
#if BIGENDIAN
    return(*(UINT32 *)(p));
#else
    return( (*p <<  24) | (*(p+1) << 16) | (*(p+2) <<  8) | *(p+3));
#endif
  }

  // Set a 64 bit integer value
  static void  Set64(UINT8 *p, UINT64 val)
  {
#if BIGENDIAN
    *(UINT64 *)(p) =val;
#else
    *p++ = (val & 0xFF00000000000000LL) >> 56;
    *p++ = (val & 0x00FF000000000000LL) >> 48;
    *p++ = (val & 0x0000FF0000000000LL) >> 40;
    *p++ = (val & 0x000000FF00000000LL) >> 32;
    *p++ = (val & 0x00000000FF000000LL) >> 24;
    *p++ = (val & 0x0000000000FF0000LL) >> 16;
    *p++ = (val & 0x000000000000FF00LL) >> 8;
    *p =   (val & 0x00000000000000FFLL);
#endif
  };

  // Get a 16 bit integer value
  static UINT64 Get64(UINT8 *p)
  {
#if BIGENDIAN
    return(*(UINT64 *)(p));
#else
    return( ((UINT64)*p <<  56) | ((UINT64)*(p+1) << 48) | ((UINT64)*(p+2) <<  40) | ((UINT64)*(p+3) << 32) |
            ((UINT64)*(p+4) << 24) | ((UINT64)*(p+5) << 16) | ((UINT64)*(p+6) << 8)| (UINT64)*(p+7)  );
#endif
  }

  // copy  Pointer to a string of bytes
  void SetP(UINT8 * pTo, UINT8 *pFrom, int length)
  {
    int i;

    for (i=1; i<= length; i++)
    {
      *pTo++ = *pFrom++;
    }
  }

  // copy Character String
  void SetString(UINT8 * pTo, UINT8 *pFrom, int length) {
	strncpy((char *)pTo, (char *)pFrom, length - 1);
	pTo[length - 1] = 0;
	
	// check for invalid UTF-8 encoding
	size_t bytesLeft = strlen((char*)pTo);
	size_t maxConvertedSize = bytesLeft * sizeof(wchar_t);
	char convBuf[maxConvertedSize];
	char* convPtr = convBuf;
	iconv_t utf8checker = iconv_open("WCHAR_T", "UTF8");
	iconv(utf8checker, (char**)&pTo, &bytesLeft, &convPtr, &maxConvertedSize);
	iconv_close(utf8checker);
	strncpy((char*)pTo, "", bytesLeft); // zero any non-zero bytes after the last valid UTF-8 character
  }

  // Record Number is always first two byes of record
  static UINT16 RecordNo(DBRecord *pRec)
  {
    return(Get16((UINT8 *)pRec));
  }
  // Record Number is always first two byes of record
  static void RecordNo(DBRecord *pRec, UINT16  val)
  {
    Set16((UINT8 *)pRec, val);
  }
};

#endif // #ifndef __DBRECORD__
